package com.xiayuxuanmin.weixinpay.utils;
import org.apache.log4j.Logger;
import org.jdom.JDOMException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 微信支付工具类
 * @Author xiayuxuanmin
 * @Date 2019/8/8
 * @Description
 */
public class PayCommonUtil {

    private static Logger logger = Logger.getLogger("wapshop_log");

    /**
     * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     * @return boolean
     */
    public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (!"sign".equals(k) && null != v && !"".equals(v)) {
                sb.append(k + "=" + v + "&");
            }
        }

        sb.append("key=" + API_KEY);

        //算出摘要
        String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();
        String tenpaySign = ((String) packageParams.get("sign")).toLowerCase();
        //System.out.println(tenpaySign + "    " + mysign);
        return tenpaySign.equals(mysign);
    }


    /**
     * 创建签名
     * @param characterEncoding 编码格式
     * @param packageParams     请求参数
     * @date 2016-4-22
     * @Description：sign签名
     */
    public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }

        sb.append("key=" + API_KEY);
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    /**
     * 获取xml数据
     * @param parameters 请求参数
     * @date 2016-4-22
     * @Description：将请求参数转换为xml格式的string
     */
    public static String getRequestXml(SortedMap<Object, Object> parameters) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
                sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
            } else {
                sb.append("<" + k + ">" + v + "</" + k + ">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    /**
     * 取出一个指定长度大小的随机正整数.
     * @param length int 设定所取出随机数的长度。length小于11
     * @return int 返回生成的随机数。
     */
    public static int buildRandom(int length) {
        int num = 1;
        double random = Math.random();
        if (random < 0.1) {
            random = random + 0.1;
        }

        for (int i = 0; i < length; i++) {
            num = num * 10;
        }
        return (int) ((random * num));
    }

    /**
     * 获取当前时间 yyyyMMddHHmmss
     * @return String
     */
    public static String getCurrTime() {
        Date now = new Date();
        SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String s = outFormat.format(now);
        return s;
    }

    /**
     * 返回给微信的参数
     * 将返回的code和message转化为xml格式
     * @param return_code
     * @param return_msg
     * @return
     */
    public static String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code
                + "]]></return_code><return_msg><![CDATA[" + return_msg
                + "]]></return_msg></xml>";
    }

    /**
     * 统一下单接口,获取微信支付二维码
     * @param out_trade_no 订单号
     * @param product_id 产品ID
     * @param body 商品描述
     * @param order_price 订单价格
     * @return
     */
    public static String weixin_pay(String out_trade_no,String product_id,String body,String order_price) throws JDOMException, IOException {
        // 账号信息
        String APPID = PayConfigUtil.APP_ID;
        // 商业号
        String MCHID= PayConfigUtil.MCH_ID;
        String KEY=  PayConfigUtil.API_KEY;
        //获取电脑发起IP
        String spbill_create_ip= PayConfigUtil.CREATE_IP;
        // 回调接口
        String notify_url= PayConfigUtil.NOTIFY_URL;
        String trade_type = "NATIVE";

        /*
        String order_price = 1; // 价格   注意：价格的单位是分
        String body = "goodssssss";   // 商品名称
        String out_trade_no = "11338"; // 订单号
        */

        String currTime = PayCommonUtil.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = PayCommonUtil.buildRandom(4) + "";
        String nonce_str = strTime + strRandom;//生成随机字符串

        //将相应的信息放到map中去
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();

        packageParams.put("appid", APPID);
        packageParams.put("mch_id", MCHID);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("total_fee", order_price);// 价格 注意：价格的单位是分
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type",trade_type);
        packageParams.put("product_id", product_id);

        //生成签名
        String sign = PayCommonUtil.createSign("UTF-8", packageParams, KEY);
        packageParams.put("sign", sign);//加密

        //将请求参数转换为xml格式的string
        String requestXML = PayCommonUtil.getRequestXml(packageParams);
        logger.info("支付请求：" + requestXML);

        //调微信的接口(在packageParams有appId等请求数据；利用packageParams加上秘钥key生成签名,这个签名里面也有请求数据，微信接受数据之后，会利用秘钥key解密，核对两个数据是否一致，来判断数据是否被篡改)
        String resXml = HttpUtil.postData(PayConfigUtil.UFDOOER_URL, requestXML);
        System.out.println(resXml);
        //解析xml
        Map map = XMLUtil.doXMLParse(resXml);
        //String return_code = (String) map.get("return_code");
        //String prepay_id = (String) map.get("prepay_id");
        //获取微信返回的二维码信息，并且返回
        String urlCode = (String)map.get("code_url");
        return urlCode;
    }
}
